package yawning.mew.cat;

import yawning.mew.ProcEffect.Trigger;
import yawning.mew.character.CharacterModel.AttackResult;
import yawning.mew.character.Druid.Talent;
import yawning.mew.sim.SimulationAction;

public class RavageAction implements SimulationAction {
	CatModelSimState mState;

	RavageAction(CatModelSimState state) {
		mState = state;
	}

	@Override
	public double perform() {
		boolean isFromStealth = false;
		double pBonusCrit = 0.0;
		int cost;

		// Stampede reduces energy cost by 50% per talent point.
		if (mState.stampedeEv.isUp()) {
			cost = mState.getEnergyCost(mState.mModel.ravageCostStampede);
		} else {
			if (mState.isInCombat()) return SimulationAction.ACTION_FAIL; // Without Stampede, can't mid-combat Ravage.

			cost = mState.getEnergyCost(mState.mModel.ravageCost);
			isFromStealth = true;
		}

		if (mState.getEnergy() < cost && !mState.oocEv.isUp()) return SimulationAction.ACTION_FAIL;

		// Predatory Strikes
		if (mState.mSimUtil.getSimTime() / mState.mSimUtil.getEndTime() < 0.8) {
			pBonusCrit = mState.mModel.druid.getTalent(Talent.PREDATORYSTRIKES) * 0.25;
		}

		AttackResult result = (isFromStealth) ? mState.mModel.getYellowStealthResult(pBonusCrit) : mState.mModel.getYellowResult(pBonusCrit);

		if (mState.mDebug) mState.DBGF("Ravage (%s)", result);

		if (result == AttackResult.MISS) {
			cost = (int) Math.round(cost * 0.2);
			mState.nrRavageMiss++;
		} else if (result == AttackResult.DODGE) {
			cost = (int) Math.round(cost * 0.2);
			mState.nrRavageDodge++;
		} else {
			// XXX: This currently varys on live depending on if Stampede is up or not.  (See LevelDepCat.java)
			double damage = mState.mModel.getWeaponDamage() * mState.mModel.levelDep.getRavageMult() + mState.mModel.levelDep.getRavageDmg();

			if (result == AttackResult.CRIT) {
				mState.nrRavageCrit++;
				damage *= mState.mModel.multCrit;
				mState.mSimUtil.triggerProc(Trigger.YELLOWCRIT);
			} else {
				mState.nrRavageHit++;
				mState.mSimUtil.triggerProc(Trigger.YELLOW);
			}

			damage *= mState.getDirectDamageMult();
			mState.ravageDamage += Math.round(damage);

			if (mState.mDebug) mState.DBGF("  Damage: %d", Math.round(damage));

			mState.onCpGenerator(result == AttackResult.CRIT);
		}

		mState.onOoCConsumer(cost);

		mState.stampedeEv.cancel();	// XXX: Not sure if misses cancel the buff.
		return 1.0;
	}
}
